iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
Software Development

遠古聖遺物改造工程:遺留系統全面重構實務指南系列 第 13

[Day 13] 應該從哪裡開始重構遺留系統?

  • 分享至 

  • xImage
  •  

應該從哪裡開始重構遺留系統?

前面已經選定目標系統使用的技術,建立一致的開發環境,也定義框架、共用元件與程式碼規範。接下來要開始實作功能,但遺留系統通常包含多條執行路徑、相依關係及尚未釐清的規則。如果只按照檔案順序或程式碼複雜度開始,很容易先完成孤立的局部程式,卻無法確認目標架構能否支撐完整功能。

本系列採用完整替換的方向。本章所說的開始重構,是開始實作目標系統,遺留系統則作為確認功能規則、輸入輸出及相容需求的來源。起點要同時考量共用基礎、功能順序與驗證方式,並且納入全部預定替換範圍,避免第一項功能完成後,才發現其他功能無法沿用相同設計。

先建立足以支援功能的共用基礎

開始實作個別功能前,應該先完成目標系統會共同使用的最小基礎。這些基礎讓後續功能採用一致的進入方式、設定、錯誤處理及測試流程,也能避免每項功能自行建立一套相似機制。

需要建立哪些基礎,要按照目標架構與實際功能決定,可能包含:

  • 建立專案骨架、程式進入點、目錄結構及模組相依規則。
  • 建立設定載入、必要欄位檢查及不同執行環境的設定方式。
  • 建立共同的錯誤分類、結果格式及必要的執行紀錄方式。
  • 如果系統需要保存資料,建立資料存取邊界、連線管理及結構變更方式。
  • 如果系統具有身分識別或存取限制,建立對應的驗證流程與使用規則。
  • 建立格式檢查、程式碼檢查、測試及建置的共同入口。

共同基礎不需要先涵蓋所有可能需求。判斷基礎是否足夠,可以檢查第一項完整功能能否直接使用、各項檢查能否重複執行,以及後續功能是否能沿用相同邊界。如果基礎元件只有預想中的用途,尚未被任何功能使用,就很難確認它的介面是否合適。

依照四項條件安排功能順序

功能的重要程度不能單獨決定實作順序。經常使用的功能可能依賴多項尚未完成的基礎,影響範圍較小的功能也可能需要複雜的資料準備。安排順序時,可以從下列四項條件一起比較:

相依關係

判斷方式

先確認功能執行前必須具備哪些項目,包括共用元件、其他功能、執行設定、初始狀態及外部相依項目。接著區分「缺少就無法執行」的必要相依,以及可以用測試替代項目或預先準備結果處理的可替代相依。如果某個項目被多項功能使用、責任範圍清楚,而且介面已經能由實際情境確認,通常要排在依賴它的功能之前。

實作步驟

  1. 列出每項功能的輸入、輸出、狀態變更,以及實際使用的組成項目。
  2. 為每個相依項目記錄提供者、使用方式、完成條件及尚未確認的問題。
  3. 按照必要相依建立先後關係,先安排會阻擋多項功能的共用基礎或功能。
  4. 如果出現循環相依,重新劃分責任或定義中間介面,找出可以獨立完成與驗證的最小範圍。
  5. 完成前置項目後,用至少一項實際功能確認其介面,再安排其餘依賴項目。

注意事項
被多項功能依賴,不代表要先做出涵蓋所有需求的大型共用元件。尚未經過實際功能驗證的設計,應該只提供目前已確認的能力。外部相依項目無法穩定控制時,也不能只因為它位於前置位置就等待完成,應該先建立可重複使用的測試替代方式,並記錄正式整合仍需符合的條件。

使用頻率

判斷方式

使用頻率要根據功能在實際情境中的觸發次數或固定週期判斷。如果系統已有執行紀錄,可以選擇具有代表性的期間進行比較。如果沒有紀錄,則可從既有操作流程、排程設定、維護文件或相關人員的說明確認。判斷時還要分開記錄觸發次數與單次處理量,避免把偶爾執行但一次處理大量內容的功能視為低使用頻率。

實作步驟

  1. 定義一致的計算單位與觀察期間,說明一次執行如何計算。
  2. 收集平常期間、集中處理期間及固定週期的執行情況,避免只看單一日期。
  3. 按照實際差異將功能分成可辨識的頻率區間,並保留資料來源與觀察限制。
  4. 從較常使用的功能中,找出規則清楚、範圍有限且能重複驗證的候選項目。
  5. 第一項功能完成後,再用實際執行結果檢查原先分類,必要時調整後續順序。

注意事項
使用頻率只能說明功能的代表性,不能直接等同實作優先順序。經常使用的功能如果具有大量未完成的相依項目,或規則仍有多種解讀,仍然要先處理阻礙。執行紀錄不足時,應該保留未知狀態與確認方式,不要用主觀印象補成精確數字。低頻功能也可能具有固定期限或較大影響,仍需與其他條件一起判斷。

影響範圍

判斷方式

影響範圍要同時檢查功能正常執行與失敗時會改變哪些流程、保存狀態、輸出結果及後續功能。如果系統由人員操作,也要確認錯誤結果會影響哪些相關人員,以及是否能及時發現與修正。影響較大、規則清楚而且結果可驗證的功能,適合及早確認目標架構能否承受實際需求。影響較大但規則不明的功能,則要先釐清預期行為與復原方式。

實作步驟

  1. 描述功能成功、拒絕處理、部分完成及執行中斷時的預期結果。
  2. 從輸入到輸出追蹤各項狀態變更,確認錯誤是否會延伸到後續功能或共用狀態。
  3. 記錄問題的發現方式、可隔離範圍、修正方式及重新執行條件。
  4. 將影響範圍與規則清楚程度一起比較,選出需要及早驗證或先行釐清的項目。
  5. 實作時先建立主要失敗情境的測試,再確認正常路徑與復原結果都符合預期。

注意事項
影響範圍大,不代表適合直接選為第一項功能。範圍過廣時,架構、規則與整合問題可能同時出現,使失敗原因難以辨識。判斷也不能只計算受影響的功能數量,還要考量狀態是否能復原、錯誤是否容易發現,以及結果是否會在後續執行中持續擴散。

資料需求

判斷方式

先確認功能需要的輸入內容、既有資料、初始狀態及預期轉換結果,並判斷這些條件能否在開發與測試情境中重複建立。除了正常範例,資料需求也要涵蓋空值、邊界值、格式差異、歷史例外及彼此關聯的狀態。只有在準備方式、預期結果與清除方式都能說明時,功能才具備可重複驗證的條件。

實作步驟

  1. 按照功能規則列出必要欄位、狀態組合、邊界情境及預期結果。
  2. 確認資料來自固定測試內容、既有資料的受控樣本,或其他可重複建立的來源。
  3. 建立資料準備、轉換、檢查及清除流程,使每次測試都能從已知狀態開始。
  4. 在實作功能前先執行資料準備流程,確認輸入與預期結果確實可重現。
  5. 將資料準備列入功能的前置條件與完成條件,並記錄尚未涵蓋的例外情況。

注意事項
程式完成不代表功能已經可以驗證。必要資料尚未準備、轉換規則未確認或初始狀態無法重現時,應該先保留為受阻項目。自行建立的測試內容可能無法呈現既有資料長期累積的例外,因此仍要選擇受控樣本檢查已知差異。使用既有資料時,還要按照實際限制移除或替換不應進入測試情境的敏感內容。

比較結果可以將功能分成需要先完成的基礎項目、適合驗證架構的代表功能、依賴前述成果的後續功能,以及資訊仍不足的待釐清功能。這項分類用來呈現先後關係,不代表後續功能可以移出替換範圍。

如果各項條件還沒有足夠資訊,不需要勉強換算成精確分數。此時應該記錄未知項目、確認方式及會影響的決定,等資訊補齊後再調整順序。沒有依據的數字只會隱藏不確定性。

選擇一項代表性的完整功能

完成最小共用基礎後,可以選擇一項範圍有限、規則相對清楚,而且會經過主要系統邊界的功能作為第一個實作目標。這項功能要涵蓋從輸入、規則判斷、必要的狀態變更,到輸出結果的完整路徑。如果系統包含資料保存或外部互動,也要涵蓋該功能實際需要的部分。

適合作為起點的功能通常符合下列條件:

  • 使用情境、輸入條件及預期結果已經能清楚描述。
  • 範圍可以在有限時間內完成,失敗時也能辨識問題位置。
  • 執行路徑會使用目標架構的重要邊界,並且形成超過單一畫面或孤立函式的完整路徑。
  • 測試資料、相依項目及驗收方式可以事先準備。
  • 完成後可以確認共用基礎與程式碼規範能否實際套用。

例如,具有操作畫面、功能規則及資料保存的系統,可以選擇一條「接收輸入、驗證內容、執行規則、保存結果、顯示結果」的功能路徑。第一階段不必涵蓋同類功能的所有變化,但每一個納入的步驟都要實際串接。對於沒有畫面或不保存資料的系統,也可以按照真正的輸入輸出與狀態變化選擇完整路徑。

只建立空白畫面、回傳固定結果或完成一個沒有相依關係的簡單函式,雖然容易完成,卻不足以驗證目標架構。相反地,直接選擇規則最多、相依範圍最廣的功能,會讓架構問題、規則問題與整合問題同時出現,難以判斷失敗原因。

避開暫時無法驗證的起點

有些功能很重要,卻不適合成為第一個實作目標。遇到下列情況時,應該先處理阻礙驗證的問題,再決定實作順序:

  • 功能規則仍有多種解讀,無法列出穩定的預期結果。
  • 功能依賴多個尚未確認或無法控制的外部項目。
  • 必要的輸入、既有資料或初始狀態無法重現。
  • 修改結果只能由人工觀察,而且目前沒有一致的判斷標準。
  • 功能會同時改變多項共用狀態,失敗後難以隔離影響。
  • 功能雖然容易完成,卻沒有使用目標架構的重要邊界,無法提供足夠的驗證結果。

這些功能不會因此失去重要性。規則不明時要先還原行為與確認需求,相依項目不可控制時要先建立可替代的測試方式,資料無法重現時要先定義準備與清除流程。阻礙解除後,再將功能放回適當順序。

用第一項功能檢查目標架構

第一項完整功能完成後,應該回頭檢查先前的架構與規範是否能支援實際程式。檢查重點包含:

  • 功能是否遵守已定義的模組責任與相依方向。
  • 共用元件是否提供必要能力,而且沒有要求功能繞過公開介面。
  • 輸入、輸出、錯誤及狀態變更是否能在既定邊界中表達。
  • 設定、測試、建置及執行方式是否能由共同入口重複執行。
  • 必要相依項目是否能在開發與測試情境中穩定準備。
  • 新增相似功能時,是否能沿用相同結構,而不必複製整套處理流程。

如果實作時持續出現例外路徑、反向相依或難以測試的隱藏狀態,應該先修正架構決定與共用基礎。第一項功能的價值,在於用實際路徑提早找出這些問題,避免相同限制擴散到後續功能。

為全部替換範圍建立實作計畫

代表性功能只能驗證起點,不能取代其餘功能的安排。要完成整套遺留系統替換,仍需列出所有納入範圍的功能與組成項目,每一項都要記錄下列資訊:

計畫項目 需要記錄的內容
前置條件 必須先完成的共用基礎、功能、規則確認或相依項目
資料準備 所需輸入、初始狀態、既有資料及必要轉換
實作範圍 本階段包含的輸入、規則、狀態變更、輸出及例外情況
驗證方式 測試情境、預期結果、驗收方式及需要比較的既有行為
整合條件 可以和哪些功能或組成項目共同執行,以及需要符合的介面
完成條件 程式、測試、設定、必要文件及檢查流程需要達到的結果

接著按照相依關係安排順序與里程碑。里程碑應該描述可以驗證的成果,例如「代表性功能已通過完整路徑測試」或「某一組互相關聯的功能已完成整合」,不能只記錄預計完成日期。每個里程碑還要標示進入條件、完成條件及未完成項目的處理方式。

部分功能完成,只能表示相應範圍已經可以驗證。要判斷目標系統能否替換遺留系統,仍需確認所有納入範圍的功能、資料準備、整合及驗收條件都已完成。這樣才能避免局部成果被誤認為整體已經具備切換條件。

開始實作前的檢查

決定第一項功能前,可以用下列問題檢查目前的選擇:

  • 是否已經建立這項功能需要的最小共用基礎?
  • 是否能清楚描述功能的使用情境、輸入、規則及預期結果?
  • 是否知道這項功能依賴哪些組成項目,以及哪些項目必須先完成?
  • 是否能準備必要資料,而且能在有限範圍內重複驗證結果?
  • 是否涵蓋目標架構的重要邊界,足以找出設計上的限制?
  • 是否已經記錄其他功能的先後關係與完成條件?
  • 是否能說明第一項功能完成後,下一個里程碑要驗證甚麼?

如果多數問題仍無法回答,應該先補齊相關資訊或縮小第一項功能的範圍。起點的目的是建立可以重複使用的實作與驗證方式,讓後續功能按照明確順序完成。

重點整理

  • 開始實作目標系統前,應該先建立足以支援功能的最小共用基礎,再以實際功能確認其介面是否合適。
  • 判斷相依關係時,要區分必要相依與可替代相依,優先完成會阻擋多項功能的前置項目,再以實際功能檢查介面。
  • 判斷使用頻率時,要採用一致的計算單位與代表性期間,分開記錄觸發次數與單次處理量,不能只靠頻率決定順序。
  • 判斷影響範圍時,要確認正常與失敗結果影響的流程、狀態及後續功能,也要考量問題能否發現、隔離與復原。
  • 判斷資料需求時,要確認輸入、既有資料、初始狀態、預期結果及清除方式都能重複建立,資料尚未準備完成的功能則保留為受阻項目。
  • 第一項功能要涵蓋完整輸入輸出路徑及重要系統邊界,而且能在有限範圍內重複驗證。
  • 規則不明、相依項目不可控制、資料無法重現或缺少判斷標準的功能,應該先排除阻礙再開始實作。
  • 第一項完整功能可以檢查模組邊界、共用元件、設定、測試及建置方式是否能支援實際需求。
  • 代表性功能完成後,仍要按照相依關係安排所有替換範圍的實作、資料準備、整合、驗收及完成條件。

上一篇
[Day 12] 程式碼應該遵循哪些規範?
下一篇
[Day 14] 如何分析原有功能?
系列文
遠古聖遺物改造工程:遺留系統全面重構實務指南14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言